home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / httplib.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2005-10-18  |  34.8 KB  |  1,305 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.4)
  3.  
  4. '''HTTP/1.1 client library
  5.  
  6. <intro stuff goes here>
  7. <other stuff, too>
  8.  
  9. HTTPConnection go through a number of "states", which defines when a client
  10. may legally make another request or fetch the response for a particular
  11. request. This diagram details these state transitions:
  12.  
  13.     (null)
  14.       |
  15.       | HTTPConnection()
  16.       v
  17.     Idle
  18.       |
  19.       | putrequest()
  20.       v
  21.     Request-started
  22.       |
  23.       | ( putheader() )*  endheaders()
  24.       v
  25.     Request-sent
  26.       |
  27.       | response = getresponse()
  28.       v
  29.     Unread-response   [Response-headers-read]
  30.       |\\____________________
  31.       |                     |
  32.       | response.read()     | putrequest()
  33.       v                     v
  34.     Idle                  Req-started-unread-response
  35.                      ______/|
  36.                    /        |
  37.    response.read() |        | ( putheader() )*  endheaders()
  38.                    v        v
  39.        Request-started    Req-sent-unread-response
  40.                             |
  41.                             | response.read()
  42.                             v
  43.                           Request-sent
  44.  
  45. This diagram presents the following rules:
  46.   -- a second request may not be started until {response-headers-read}
  47.   -- a response [object] cannot be retrieved until {request-sent}
  48.   -- there is no differentiation between an unread response body and a
  49.      partially read response body
  50.  
  51. Note: this enforcement is applied by the HTTPConnection class. The
  52.       HTTPResponse class does not enforce this state machine, which
  53.       implies sophisticated clients may accelerate the request/response
  54.       pipeline. Caution should be taken, though: accelerating the states
  55.       beyond the above pattern may imply knowledge of the server\'s
  56.       connection-close behavior for certain requests. For example, it
  57.       is impossible to tell whether the server will close the connection
  58.       UNTIL the response headers have been read; this means that further
  59.       requests cannot be placed into the pipeline until it is known that
  60.       the server will NOT be closing the connection.
  61.  
  62. Logical State                  __state            __response
  63. -------------                  -------            ----------
  64. Idle                           _CS_IDLE           None
  65. Request-started                _CS_REQ_STARTED    None
  66. Request-sent                   _CS_REQ_SENT       None
  67. Unread-response                _CS_IDLE           <response_class>
  68. Req-started-unread-response    _CS_REQ_STARTED    <response_class>
  69. Req-sent-unread-response       _CS_REQ_SENT       <response_class>
  70. '''
  71. import errno
  72. import mimetools
  73. import socket
  74. from urlparse import urlsplit
  75.  
  76. try:
  77.     from cStringIO import StringIO
  78. except ImportError:
  79.     from StringIO import StringIO
  80.  
  81. __all__ = [
  82.     'HTTP',
  83.     'HTTPResponse',
  84.     'HTTPConnection',
  85.     'HTTPSConnection',
  86.     'HTTPException',
  87.     'NotConnected',
  88.     'UnknownProtocol',
  89.     'UnknownTransferEncoding',
  90.     'UnimplementedFileMode',
  91.     'IncompleteRead',
  92.     'InvalidURL',
  93.     'ImproperConnectionState',
  94.     'CannotSendRequest',
  95.     'CannotSendHeader',
  96.     'ResponseNotReady',
  97.     'BadStatusLine',
  98.     'error']
  99. HTTP_PORT = 80
  100. HTTPS_PORT = 443
  101. _UNKNOWN = 'UNKNOWN'
  102. _CS_IDLE = 'Idle'
  103. _CS_REQ_STARTED = 'Request-started'
  104. _CS_REQ_SENT = 'Request-sent'
  105. CONTINUE = 100
  106. SWITCHING_PROTOCOLS = 101
  107. PROCESSING = 102
  108. OK = 200
  109. CREATED = 201
  110. ACCEPTED = 202
  111. NON_AUTHORITATIVE_INFORMATION = 203
  112. NO_CONTENT = 204
  113. RESET_CONTENT = 205
  114. PARTIAL_CONTENT = 206
  115. MULTI_STATUS = 207
  116. IM_USED = 226
  117. MULTIPLE_CHOICES = 300
  118. MOVED_PERMANENTLY = 301
  119. FOUND = 302
  120. SEE_OTHER = 303
  121. NOT_MODIFIED = 304
  122. USE_PROXY = 305
  123. TEMPORARY_REDIRECT = 307
  124. BAD_REQUEST = 400
  125. UNAUTHORIZED = 401
  126. PAYMENT_REQUIRED = 402
  127. FORBIDDEN = 403
  128. NOT_FOUND = 404
  129. METHOD_NOT_ALLOWED = 405
  130. NOT_ACCEPTABLE = 406
  131. PROXY_AUTHENTICATION_REQUIRED = 407
  132. REQUEST_TIMEOUT = 408
  133. CONFLICT = 409
  134. GONE = 410
  135. LENGTH_REQUIRED = 411
  136. PRECONDITION_FAILED = 412
  137. REQUEST_ENTITY_TOO_LARGE = 413
  138. REQUEST_URI_TOO_LONG = 414
  139. UNSUPPORTED_MEDIA_TYPE = 415
  140. REQUESTED_RANGE_NOT_SATISFIABLE = 416
  141. EXPECTATION_FAILED = 417
  142. UNPROCESSABLE_ENTITY = 422
  143. LOCKED = 423
  144. FAILED_DEPENDENCY = 424
  145. UPGRADE_REQUIRED = 426
  146. INTERNAL_SERVER_ERROR = 500
  147. NOT_IMPLEMENTED = 501
  148. BAD_GATEWAY = 502
  149. SERVICE_UNAVAILABLE = 503
  150. GATEWAY_TIMEOUT = 504
  151. HTTP_VERSION_NOT_SUPPORTED = 505
  152. INSUFFICIENT_STORAGE = 507
  153. NOT_EXTENDED = 510
  154.  
  155. class HTTPMessage(mimetools.Message):
  156.     
  157.     def addheader(self, key, value):
  158.         '''Add header for field key handling repeats.'''
  159.         prev = self.dict.get(key)
  160.         if prev is None:
  161.             self.dict[key] = value
  162.         else:
  163.             combined = ', '.join((prev, value))
  164.             self.dict[key] = combined
  165.  
  166.     
  167.     def addcontinue(self, key, more):
  168.         '''Add more field data from a continuation line.'''
  169.         prev = self.dict[key]
  170.         self.dict[key] = prev + '\n ' + more
  171.  
  172.     
  173.     def readheaders(self):
  174.         '''Read header lines.
  175.  
  176.         Read header lines up to the entirely blank line that terminates them.
  177.         The (normally blank) line that ends the headers is skipped, but not
  178.         included in the returned list.  If a non-header line ends the headers,
  179.         (which is an error), an attempt is made to backspace over it; it is
  180.         never included in the returned list.
  181.  
  182.         The variable self.status is set to the empty string if all went well,
  183.         otherwise it is an error message.  The variable self.headers is a
  184.         completely uninterpreted list of lines contained in the header (so
  185.         printing them will reproduce the header exactly as it appears in the
  186.         file).
  187.  
  188.         If multiple header fields with the same name occur, they are combined
  189.         according to the rules in RFC 2616 sec 4.2:
  190.  
  191.         Appending each subsequent field-value to the first, each separated
  192.         by a comma. The order in which header fields with the same field-name
  193.         are received is significant to the interpretation of the combined
  194.         field value.
  195.         '''
  196.         self.dict = { }
  197.         self.unixfrom = ''
  198.         self.headers = hlist = []
  199.         self.status = ''
  200.         headerseen = ''
  201.         firstline = 1
  202.         startofline = None
  203.         unread = None
  204.         tell = None
  205.         if hasattr(self.fp, 'unread'):
  206.             unread = self.fp.unread
  207.         elif self.seekable:
  208.             tell = self.fp.tell
  209.         
  210.         while True:
  211.             if tell:
  212.                 
  213.                 try:
  214.                     startofline = tell()
  215.                 except IOError:
  216.                     startofline = None
  217.                     tell = None
  218.                     self.seekable = 0
  219.                 except:
  220.                     None<EXCEPTION MATCH>IOError
  221.                 
  222.  
  223.             None<EXCEPTION MATCH>IOError
  224.             line = self.fp.readline()
  225.             if not line:
  226.                 self.status = 'EOF in headers'
  227.                 break
  228.             
  229.             if firstline and line.startswith('From '):
  230.                 self.unixfrom = self.unixfrom + line
  231.                 continue
  232.             
  233.             firstline = 0
  234.             if headerseen and line[0] in ' \t':
  235.                 hlist.append(line)
  236.                 self.addcontinue(headerseen, line.strip())
  237.                 continue
  238.             elif self.iscomment(line):
  239.                 continue
  240.             elif self.islast(line):
  241.                 break
  242.             
  243.             headerseen = self.isheader(line)
  244.             if headerseen:
  245.                 hlist.append(line)
  246.                 self.addheader(headerseen, line[len(headerseen) + 1:].strip())
  247.                 continue
  248.                 continue
  249.             if not self.dict:
  250.                 self.status = 'No headers'
  251.             else:
  252.                 self.status = 'Non-header line where header expected'
  253.             if unread:
  254.                 unread(line)
  255.             elif tell:
  256.                 self.fp.seek(startofline)
  257.             else:
  258.                 self.status = self.status + '; bad seek'
  259.             break
  260.  
  261.  
  262.  
  263. class HTTPResponse:
  264.     
  265.     def __init__(self, sock, debuglevel = 0, strict = 0, method = None):
  266.         self.fp = sock.makefile('rb', 0)
  267.         self.debuglevel = debuglevel
  268.         self.strict = strict
  269.         self._method = method
  270.         self.msg = None
  271.         self.version = _UNKNOWN
  272.         self.status = _UNKNOWN
  273.         self.reason = _UNKNOWN
  274.         self.chunked = _UNKNOWN
  275.         self.chunk_left = _UNKNOWN
  276.         self.length = _UNKNOWN
  277.         self.will_close = _UNKNOWN
  278.  
  279.     
  280.     def _read_status(self):
  281.         line = self.fp.readline()
  282.         if self.debuglevel > 0:
  283.             print 'reply:', repr(line)
  284.         
  285.         if not line:
  286.             raise BadStatusLine(line)
  287.         
  288.         
  289.         try:
  290.             (version, status, reason) = line.split(None, 2)
  291.         except ValueError:
  292.             
  293.             try:
  294.                 (version, status) = line.split(None, 1)
  295.                 reason = ''
  296.             except ValueError:
  297.                 version = ''
  298.             except:
  299.                 None<EXCEPTION MATCH>ValueError
  300.             
  301.  
  302.             None<EXCEPTION MATCH>ValueError
  303.  
  304.         if not version.startswith('HTTP/'):
  305.             if self.strict:
  306.                 self.close()
  307.                 raise BadStatusLine(line)
  308.             else:
  309.                 self.fp = LineAndFileWrapper(line, self.fp)
  310.                 return ('HTTP/0.9', 200, '')
  311.         
  312.         
  313.         try:
  314.             status = int(status)
  315.             if status < 100 or status > 999:
  316.                 raise BadStatusLine(line)
  317.         except ValueError:
  318.             raise BadStatusLine(line)
  319.  
  320.         return (version, status, reason)
  321.  
  322.     
  323.     def begin(self):
  324.         if self.msg is not None:
  325.             return None
  326.         
  327.         while True:
  328.             (version, status, reason) = self._read_status()
  329.             if status != CONTINUE:
  330.                 break
  331.             
  332.             while True:
  333.                 skip = self.fp.readline().strip()
  334.                 if not skip:
  335.                     break
  336.                 
  337.                 if self.debuglevel > 0:
  338.                     print 'header:', skip
  339.                     continue
  340.         self.status = status
  341.         self.reason = reason.strip()
  342.         if version == 'HTTP/1.0':
  343.             self.version = 10
  344.         elif version.startswith('HTTP/1.'):
  345.             self.version = 11
  346.         elif version == 'HTTP/0.9':
  347.             self.version = 9
  348.         else:
  349.             raise UnknownProtocol(version)
  350.         if self.version == 9:
  351.             self.length = None
  352.             self.chunked = 0
  353.             self.will_close = 1
  354.             self.msg = HTTPMessage(StringIO())
  355.             return None
  356.         
  357.         self.msg = HTTPMessage(self.fp, 0)
  358.         if self.debuglevel > 0:
  359.             for hdr in self.msg.headers:
  360.                 print 'header:', hdr,
  361.             
  362.         
  363.         self.msg.fp = None
  364.         tr_enc = self.msg.getheader('transfer-encoding')
  365.         if tr_enc and tr_enc.lower() == 'chunked':
  366.             self.chunked = 1
  367.             self.chunk_left = None
  368.         else:
  369.             self.chunked = 0
  370.         self.will_close = self._check_close()
  371.         length = self.msg.getheader('content-length')
  372.         if length and not (self.chunked):
  373.             
  374.             try:
  375.                 self.length = int(length)
  376.             except ValueError:
  377.                 self.length = None
  378.             except:
  379.                 None<EXCEPTION MATCH>ValueError
  380.             
  381.  
  382.         None<EXCEPTION MATCH>ValueError
  383.         self.length = None
  384.         if not status == NO_CONTENT and status == NOT_MODIFIED:
  385.             if status <= status:
  386.                 pass
  387.             elif status < 200 or self._method == 'HEAD':
  388.                 self.length = 0
  389.             
  390.         if not (self.will_close) and not (self.chunked) and self.length is None:
  391.             self.will_close = 1
  392.         
  393.  
  394.     
  395.     def _check_close(self):
  396.         conn = self.msg.getheader('connection')
  397.         if self.version == 11:
  398.             conn = self.msg.getheader('connection')
  399.             if conn and 'close' in conn.lower():
  400.                 return True
  401.             
  402.             return False
  403.         
  404.         if self.msg.getheader('keep-alive'):
  405.             return False
  406.         
  407.         if conn and 'keep-alive' in conn.lower():
  408.             return False
  409.         
  410.         pconn = self.msg.getheader('proxy-connection')
  411.         if pconn and 'keep-alive' in pconn.lower():
  412.             return False
  413.         
  414.         return True
  415.  
  416.     
  417.     def close(self):
  418.         if self.fp:
  419.             self.fp.close()
  420.             self.fp = None
  421.         
  422.  
  423.     
  424.     def isclosed(self):
  425.         return self.fp is None
  426.  
  427.     
  428.     def read(self, amt = None):
  429.         if self.fp is None:
  430.             return ''
  431.         
  432.         if self.chunked:
  433.             return self._read_chunked(amt)
  434.         
  435.         if amt is None:
  436.             if self.length is None:
  437.                 s = self.fp.read()
  438.             else:
  439.                 s = self._safe_read(self.length)
  440.                 self.length = 0
  441.             self.close()
  442.             return s
  443.         
  444.         if self.length is not None:
  445.             if amt > self.length:
  446.                 amt = self.length
  447.             
  448.         
  449.         s = self.fp.read(amt)
  450.         if self.length is not None:
  451.             self.length -= len(s)
  452.         
  453.         return s
  454.  
  455.     
  456.     def _read_chunked(self, amt):
  457.         chunk_left = self.chunk_left
  458.         value = ''
  459.         while True:
  460.             if chunk_left is None:
  461.                 line = self.fp.readline()
  462.                 i = line.find(';')
  463.                 if i >= 0:
  464.                     line = line[:i]
  465.                 
  466.                 chunk_left = int(line, 16)
  467.                 if chunk_left == 0:
  468.                     break
  469.                 
  470.             
  471.             if amt is None:
  472.                 value += self._safe_read(chunk_left)
  473.             elif amt < chunk_left:
  474.                 value += self._safe_read(amt)
  475.                 self.chunk_left = chunk_left - amt
  476.                 return value
  477.             elif amt == chunk_left:
  478.                 value += self._safe_read(amt)
  479.                 self._safe_read(2)
  480.                 self.chunk_left = None
  481.                 return value
  482.             else:
  483.                 value += self._safe_read(chunk_left)
  484.                 amt -= chunk_left
  485.             self._safe_read(2)
  486.             chunk_left = None
  487.         while True:
  488.             line = self.fp.readline()
  489.             if line == '\r\n':
  490.                 break
  491.                 continue
  492.         self.close()
  493.         return value
  494.  
  495.     
  496.     def _safe_read(self, amt):
  497.         '''Read the number of bytes requested, compensating for partial reads.
  498.  
  499.         Normally, we have a blocking socket, but a read() can be interrupted
  500.         by a signal (resulting in a partial read).
  501.  
  502.         Note that we cannot distinguish between EOF and an interrupt when zero
  503.         bytes have been read. IncompleteRead() will be raised in this
  504.         situation.
  505.  
  506.         This function should be used when <amt> bytes "should" be present for
  507.         reading. If the bytes are truly not available (due to EOF), then the
  508.         IncompleteRead exception can be used to detect the problem.
  509.         '''
  510.         s = ''
  511.         while amt > 0:
  512.             chunk = self.fp.read(amt)
  513.             if not chunk:
  514.                 raise IncompleteRead(s)
  515.             
  516.             s += chunk
  517.             amt -= len(chunk)
  518.         return s
  519.  
  520.     
  521.     def getheader(self, name, default = None):
  522.         if self.msg is None:
  523.             raise ResponseNotReady()
  524.         
  525.         return self.msg.getheader(name, default)
  526.  
  527.     
  528.     def getheaders(self):
  529.         '''Return list of (header, value) tuples.'''
  530.         if self.msg is None:
  531.             raise ResponseNotReady()
  532.         
  533.         return self.msg.items()
  534.  
  535.  
  536.  
  537. class HTTPConnection:
  538.     _http_vsn = 11
  539.     _http_vsn_str = 'HTTP/1.1'
  540.     response_class = HTTPResponse
  541.     default_port = HTTP_PORT
  542.     auto_open = 1
  543.     debuglevel = 0
  544.     strict = 0
  545.     
  546.     def __init__(self, host, port = None, strict = None):
  547.         self.sock = None
  548.         self._buffer = []
  549.         self._HTTPConnection__response = None
  550.         self._HTTPConnection__state = _CS_IDLE
  551.         self._method = None
  552.         self._set_hostport(host, port)
  553.         if strict is not None:
  554.             self.strict = strict
  555.         
  556.  
  557.     
  558.     def _set_hostport(self, host, port):
  559.         if port is None:
  560.             i = host.rfind(':')
  561.             j = host.rfind(']')
  562.             if i > j:
  563.                 
  564.                 try:
  565.                     port = int(host[i + 1:])
  566.                 except ValueError:
  567.                     raise InvalidURL("nonnumeric port: '%s'" % host[i + 1:])
  568.  
  569.                 host = host[:i]
  570.             else:
  571.                 port = self.default_port
  572.             if host and host[0] == '[' and host[-1] == ']':
  573.                 host = host[1:-1]
  574.             
  575.         
  576.         self.host = host
  577.         self.port = port
  578.  
  579.     
  580.     def set_debuglevel(self, level):
  581.         self.debuglevel = level
  582.  
  583.     
  584.     def connect(self):
  585.         '''Connect to the host and port specified in __init__.'''
  586.         msg = 'getaddrinfo returns an empty list'
  587.         for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
  588.             (af, socktype, proto, canonname, sa) = res
  589.             
  590.             try:
  591.                 self.sock = socket.socket(af, socktype, proto)
  592.                 if self.debuglevel > 0:
  593.                     print 'connect: (%s, %s)' % (self.host, self.port)
  594.                 
  595.                 self.sock.connect(sa)
  596.             except socket.error:
  597.                 msg = None
  598.                 if self.debuglevel > 0:
  599.                     print 'connect fail:', (self.host, self.port)
  600.                 
  601.                 if self.sock:
  602.                     self.sock.close()
  603.                 
  604.                 self.sock = None
  605.                 continue
  606.  
  607.         
  608.         if not self.sock:
  609.             raise socket.error, msg
  610.         
  611.  
  612.     
  613.     def close(self):
  614.         '''Close the connection to the HTTP server.'''
  615.         if self.sock:
  616.             self.sock.close()
  617.             self.sock = None
  618.         
  619.         if self._HTTPConnection__response:
  620.             self._HTTPConnection__response.close()
  621.             self._HTTPConnection__response = None
  622.         
  623.         self._HTTPConnection__state = _CS_IDLE
  624.  
  625.     
  626.     def send(self, str):
  627.         """Send `str' to the server."""
  628.         if self.sock is None:
  629.             if self.auto_open:
  630.                 self.connect()
  631.             else:
  632.                 raise NotConnected()
  633.         
  634.         if self.debuglevel > 0:
  635.             print 'send:', repr(str)
  636.         
  637.         
  638.         try:
  639.             self.sock.sendall(str)
  640.         except socket.error:
  641.             v = None
  642.             if v[0] == 32:
  643.                 self.close()
  644.             
  645.             raise 
  646.  
  647.  
  648.     
  649.     def _output(self, s):
  650.         '''Add a line of output to the current request buffer.
  651.  
  652.         Assumes that the line does *not* end with \\r\\n.
  653.         '''
  654.         self._buffer.append(s)
  655.  
  656.     
  657.     def _send_output(self):
  658.         '''Send the currently buffered request and clear the buffer.
  659.  
  660.         Appends an extra \\r\\n to the buffer.
  661.         '''
  662.         self._buffer.extend(('', ''))
  663.         msg = '\r\n'.join(self._buffer)
  664.         del self._buffer[:]
  665.         self.send(msg)
  666.  
  667.     
  668.     def putrequest(self, method, url, skip_host = 0, skip_accept_encoding = 0):
  669.         """Send a request to the server.
  670.  
  671.         `method' specifies an HTTP request method, e.g. 'GET'.
  672.         `url' specifies the object being requested, e.g. '/index.html'.
  673.         `skip_host' if True does not add automatically a 'Host:' header
  674.         `skip_accept_encoding' if True does not add automatically an
  675.            'Accept-Encoding:' header
  676.         """
  677.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  678.             self._HTTPConnection__response = None
  679.         
  680.         if self._HTTPConnection__state == _CS_IDLE:
  681.             self._HTTPConnection__state = _CS_REQ_STARTED
  682.         else:
  683.             raise CannotSendRequest()
  684.         self._method = method
  685.         if not url:
  686.             url = '/'
  687.         
  688.         str = '%s %s %s' % (method, url, self._http_vsn_str)
  689.         self._output(str)
  690.         if self._http_vsn == 11:
  691.             if not skip_host:
  692.                 netloc = ''
  693.                 if url.startswith('http'):
  694.                     (nil, netloc, nil, nil, nil) = urlsplit(url)
  695.                 
  696.                 if netloc:
  697.                     self.putheader('Host', netloc.encode('idna'))
  698.                 elif self.port == HTTP_PORT:
  699.                     self.putheader('Host', self.host.encode('idna'))
  700.                 else:
  701.                     self.putheader('Host', '%s:%s' % (self.host.encode('idna'), self.port))
  702.             
  703.             if not skip_accept_encoding:
  704.                 self.putheader('Accept-Encoding', 'identity')
  705.             
  706.         
  707.  
  708.     
  709.     def putheader(self, header, value):
  710.         """Send a request header line to the server.
  711.  
  712.         For example: h.putheader('Accept', 'text/html')
  713.         """
  714.         if self._HTTPConnection__state != _CS_REQ_STARTED:
  715.             raise CannotSendHeader()
  716.         
  717.         str = '%s: %s' % (header, value)
  718.         self._output(str)
  719.  
  720.     
  721.     def endheaders(self):
  722.         '''Indicate that the last header line has been sent to the server.'''
  723.         if self._HTTPConnection__state == _CS_REQ_STARTED:
  724.             self._HTTPConnection__state = _CS_REQ_SENT
  725.         else:
  726.             raise CannotSendHeader()
  727.         self._send_output()
  728.  
  729.     
  730.     def request(self, method, url, body = None, headers = { }):
  731.         '''Send a complete request to the server.'''
  732.         
  733.         try:
  734.             self._send_request(method, url, body, headers)
  735.         except socket.error:
  736.             v = None
  737.             if v[0] != 32 or not (self.auto_open):
  738.                 raise 
  739.             
  740.             self._send_request(method, url, body, headers)
  741.  
  742.  
  743.     
  744.     def _send_request(self, method, url, body, headers):
  745.         header_names = []([ k.lower() for k in headers ])
  746.         skips = { }
  747.         if 'accept-encoding' in header_names:
  748.             skips['skip_accept_encoding'] = 1
  749.         
  750.         self.putrequest(method, url, **skips)
  751.         if body and 'content-length' not in header_names:
  752.             self.putheader('Content-Length', str(len(body)))
  753.         
  754.         for hdr, value in headers.iteritems():
  755.             self.putheader(hdr, value)
  756.         
  757.         self.endheaders()
  758.         if body:
  759.             self.send(body)
  760.         
  761.  
  762.     
  763.     def getresponse(self):
  764.         '''Get the response from the server.'''
  765.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  766.             self._HTTPConnection__response = None
  767.         
  768.         if self._HTTPConnection__state != _CS_REQ_SENT or self._HTTPConnection__response:
  769.             raise ResponseNotReady()
  770.         
  771.         if self.debuglevel > 0:
  772.             response = self.response_class(self.sock, self.debuglevel, strict = self.strict, method = self._method)
  773.         else:
  774.             response = self.response_class(self.sock, strict = self.strict, method = self._method)
  775.         response.begin()
  776.         self._HTTPConnection__state = _CS_IDLE
  777.         if response.will_close:
  778.             self.close()
  779.         else:
  780.             self._HTTPConnection__response = response
  781.         return response
  782.  
  783.  
  784.  
  785. class SharedSocket:
  786.     
  787.     def __init__(self, sock):
  788.         self.sock = sock
  789.         self._refcnt = 0
  790.  
  791.     
  792.     def incref(self):
  793.         self._refcnt += 1
  794.  
  795.     
  796.     def decref(self):
  797.         self._refcnt -= 1
  798.         if self._refcnt == 0:
  799.             self.sock.close()
  800.         
  801.  
  802.     
  803.     def __del__(self):
  804.         self.sock.close()
  805.  
  806.  
  807.  
  808. class SharedSocketClient:
  809.     
  810.     def __init__(self, shared):
  811.         self._closed = 0
  812.         self._shared = shared
  813.         self._shared.incref()
  814.         self._sock = shared.sock
  815.  
  816.     
  817.     def close(self):
  818.         if not self._closed:
  819.             self._shared.decref()
  820.             self._closed = 1
  821.             self._shared = None
  822.         
  823.  
  824.  
  825.  
  826. class SSLFile(SharedSocketClient):
  827.     '''File-like object wrapping an SSL socket.'''
  828.     BUFSIZE = 8192
  829.     
  830.     def __init__(self, sock, ssl, bufsize = None):
  831.         SharedSocketClient.__init__(self, sock)
  832.         self._ssl = ssl
  833.         self._buf = ''
  834.         if not bufsize:
  835.             pass
  836.         self._bufsize = self.__class__.BUFSIZE
  837.  
  838.     
  839.     def _read(self):
  840.         buf = ''
  841.         while True:
  842.             
  843.             try:
  844.                 buf = self._ssl.read(self._bufsize)
  845.             except socket.sslerror:
  846.                 err = None
  847.                 if err[0] == socket.SSL_ERROR_WANT_READ or err[0] == socket.SSL_ERROR_WANT_WRITE:
  848.                     continue
  849.                 
  850.                 if err[0] == socket.SSL_ERROR_ZERO_RETURN or err[0] == socket.SSL_ERROR_EOF:
  851.                     break
  852.                 
  853.                 raise 
  854.                 continue
  855.                 except socket.error:
  856.                     err = None
  857.                     if err[0] == errno.EINTR:
  858.                         continue
  859.                     
  860.                     if err[0] == errno.EBADF:
  861.                         break
  862.                     
  863.                     raise 
  864.                     continue
  865.                 else:
  866.                     break
  867.                 None<EXCEPTION MATCH>socket.error
  868.             return buf
  869.  
  870.  
  871.     
  872.     def read(self, size = None):
  873.         L = [
  874.             self._buf]
  875.         avail = len(self._buf)
  876.         while size is None or avail < size:
  877.             s = self._read()
  878.             if s == '':
  879.                 break
  880.             
  881.             L.append(s)
  882.             avail += len(s)
  883.         all = ''.join(L)
  884.         if size is None:
  885.             self._buf = ''
  886.             return all
  887.         else:
  888.             self._buf = all[size:]
  889.             return all[:size]
  890.  
  891.     
  892.     def readline(self):
  893.         L = [
  894.             self._buf]
  895.         self._buf = ''
  896.         while None:
  897.             i = L[-1].find('\n')
  898.             if i >= 0:
  899.                 break
  900.             
  901.             s = self._read()
  902.             if s == '':
  903.                 break
  904.             
  905.         if i == -1:
  906.             return ''.join(L)
  907.         else:
  908.             all = ''.join(L)
  909.             i = all.find('\n') + 1
  910.             line = all[:i]
  911.             self._buf = all[i:]
  912.             return line
  913.  
  914.     
  915.     def readlines(self, sizehint = 0):
  916.         total = 0
  917.         list = []
  918.         while True:
  919.             line = self.readline()
  920.             if not line:
  921.                 break
  922.             
  923.             list.append(line)
  924.             total += len(line)
  925.             if sizehint and total >= sizehint:
  926.                 break
  927.                 continue
  928.         return list
  929.  
  930.     
  931.     def fileno(self):
  932.         return self._sock.fileno()
  933.  
  934.     
  935.     def __iter__(self):
  936.         return self
  937.  
  938.     
  939.     def next(self):
  940.         line = self.readline()
  941.         if not line:
  942.             raise StopIteration
  943.         
  944.         return line
  945.  
  946.  
  947.  
  948. class FakeSocket(SharedSocketClient):
  949.     
  950.     class _closedsocket:
  951.         
  952.         def __getattr__(self, name):
  953.             raise error(9, 'Bad file descriptor')
  954.  
  955.  
  956.     
  957.     def __init__(self, sock, ssl):
  958.         sock = SharedSocket(sock)
  959.         SharedSocketClient.__init__(self, sock)
  960.         self._ssl = ssl
  961.  
  962.     
  963.     def close(self):
  964.         SharedSocketClient.close(self)
  965.         self._sock = self.__class__._closedsocket()
  966.  
  967.     
  968.     def makefile(self, mode, bufsize = None):
  969.         if mode != 'r' and mode != 'rb':
  970.             raise UnimplementedFileMode()
  971.         
  972.         return SSLFile(self._shared, self._ssl, bufsize)
  973.  
  974.     
  975.     def send(self, stuff, flags = 0):
  976.         return self._ssl.write(stuff)
  977.  
  978.     sendall = send
  979.     
  980.     def recv(self, len = 1024, flags = 0):
  981.         return self._ssl.read(len)
  982.  
  983.     
  984.     def __getattr__(self, attr):
  985.         return getattr(self._sock, attr)
  986.  
  987.  
  988.  
  989. class HTTPSConnection(HTTPConnection):
  990.     '''This class allows communication via SSL.'''
  991.     default_port = HTTPS_PORT
  992.     
  993.     def __init__(self, host, port = None, key_file = None, cert_file = None, strict = None):
  994.         HTTPConnection.__init__(self, host, port, strict)
  995.         self.key_file = key_file
  996.         self.cert_file = cert_file
  997.  
  998.     
  999.     def connect(self):
  1000.         '''Connect to a host on a given (SSL) port.'''
  1001.         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  1002.         sock.connect((self.host, self.port))
  1003.         ssl = socket.ssl(sock, self.key_file, self.cert_file)
  1004.         self.sock = FakeSocket(sock, ssl)
  1005.  
  1006.  
  1007.  
  1008. class HTTP:
  1009.     '''Compatibility class with httplib.py from 1.5.'''
  1010.     _http_vsn = 10
  1011.     _http_vsn_str = 'HTTP/1.0'
  1012.     debuglevel = 0
  1013.     _connection_class = HTTPConnection
  1014.     
  1015.     def __init__(self, host = '', port = None, strict = None):
  1016.         '''Provide a default host, since the superclass requires one.'''
  1017.         if port == 0:
  1018.             port = None
  1019.         
  1020.         self._setup(self._connection_class(host, port, strict))
  1021.  
  1022.     
  1023.     def _setup(self, conn):
  1024.         self._conn = conn
  1025.         self.send = conn.send
  1026.         self.putrequest = conn.putrequest
  1027.         self.endheaders = conn.endheaders
  1028.         self.set_debuglevel = conn.set_debuglevel
  1029.         conn._http_vsn = self._http_vsn
  1030.         conn._http_vsn_str = self._http_vsn_str
  1031.         self.file = None
  1032.  
  1033.     
  1034.     def connect(self, host = None, port = None):
  1035.         """Accept arguments to set the host/port, since the superclass doesn't."""
  1036.         if host is not None:
  1037.             self._conn._set_hostport(host, port)
  1038.         
  1039.         self._conn.connect()
  1040.  
  1041.     
  1042.     def getfile(self):
  1043.         """Provide a getfile, since the superclass' does not use this concept."""
  1044.         return self.file
  1045.  
  1046.     
  1047.     def putheader(self, header, *values):
  1048.         '''The superclass allows only one value argument.'''
  1049.         self._conn.putheader(header, '\r\n\t'.join(values))
  1050.  
  1051.     
  1052.     def getreply(self):
  1053.         '''Compat definition since superclass does not define it.
  1054.  
  1055.         Returns a tuple consisting of:
  1056.         - server status code (e.g. \'200\' if all goes well)
  1057.         - server "reason" corresponding to status code
  1058.         - any RFC822 headers in the response from the server
  1059.         '''
  1060.         
  1061.         try:
  1062.             response = self._conn.getresponse()
  1063.         except BadStatusLine:
  1064.             e = None
  1065.             self.file = self._conn.sock.makefile('rb', 0)
  1066.             self.close()
  1067.             self.headers = None
  1068.             return (-1, e.line, None)
  1069.  
  1070.         self.headers = response.msg
  1071.         self.file = response.fp
  1072.         return (response.status, response.reason, response.msg)
  1073.  
  1074.     
  1075.     def close(self):
  1076.         self._conn.close()
  1077.         self.file = None
  1078.  
  1079.  
  1080. if hasattr(socket, 'ssl'):
  1081.     
  1082.     class HTTPS(HTTP):
  1083.         '''Compatibility with 1.5 httplib interface
  1084.  
  1085.         Python 1.5.2 did not have an HTTPS class, but it defined an
  1086.         interface for sending http requests that is also useful for
  1087.         https.
  1088.         '''
  1089.         _connection_class = HTTPSConnection
  1090.         
  1091.         def __init__(self, host = '', port = None, key_file = None, cert_file = None, strict = None):
  1092.             if port == 0:
  1093.                 port = None
  1094.             
  1095.             self._setup(self._connection_class(host, port, key_file, cert_file, strict))
  1096.             self.key_file = key_file
  1097.             self.cert_file = cert_file
  1098.  
  1099.  
  1100.  
  1101.  
  1102. class HTTPException(Exception):
  1103.     pass
  1104.  
  1105.  
  1106. class NotConnected(HTTPException):
  1107.     pass
  1108.  
  1109.  
  1110. class InvalidURL(HTTPException):
  1111.     pass
  1112.  
  1113.  
  1114. class UnknownProtocol(HTTPException):
  1115.     
  1116.     def __init__(self, version):
  1117.         self.args = (version,)
  1118.         self.version = version
  1119.  
  1120.  
  1121.  
  1122. class UnknownTransferEncoding(HTTPException):
  1123.     pass
  1124.  
  1125.  
  1126. class UnimplementedFileMode(HTTPException):
  1127.     pass
  1128.  
  1129.  
  1130. class IncompleteRead(HTTPException):
  1131.     
  1132.     def __init__(self, partial):
  1133.         self.args = (partial,)
  1134.         self.partial = partial
  1135.  
  1136.  
  1137.  
  1138. class ImproperConnectionState(HTTPException):
  1139.     pass
  1140.  
  1141.  
  1142. class CannotSendRequest(ImproperConnectionState):
  1143.     pass
  1144.  
  1145.  
  1146. class CannotSendHeader(ImproperConnectionState):
  1147.     pass
  1148.  
  1149.  
  1150. class ResponseNotReady(ImproperConnectionState):
  1151.     pass
  1152.  
  1153.  
  1154. class BadStatusLine(HTTPException):
  1155.     
  1156.     def __init__(self, line):
  1157.         self.args = (line,)
  1158.         self.line = line
  1159.  
  1160.  
  1161. error = HTTPException
  1162.  
  1163. class LineAndFileWrapper:
  1164.     '''A limited file-like object for HTTP/0.9 responses.'''
  1165.     
  1166.     def __init__(self, line, file):
  1167.         self._line = line
  1168.         self._file = file
  1169.         self._line_consumed = 0
  1170.         self._line_offset = 0
  1171.         self._line_left = len(line)
  1172.  
  1173.     
  1174.     def __getattr__(self, attr):
  1175.         return getattr(self._file, attr)
  1176.  
  1177.     
  1178.     def _done(self):
  1179.         self._line_consumed = 1
  1180.         self.read = self._file.read
  1181.         self.readline = self._file.readline
  1182.         self.readlines = self._file.readlines
  1183.  
  1184.     
  1185.     def read(self, amt = None):
  1186.         if self._line_consumed:
  1187.             return self._file.read(amt)
  1188.         
  1189.         if amt is None or amt > self._line_left:
  1190.             s = self._line[self._line_offset:]
  1191.             self._done()
  1192.             if amt is None:
  1193.                 return s + self._file.read()
  1194.             else:
  1195.                 return s + self._file.read(amt - len(s))
  1196.         else:
  1197.             i = self._line_offset
  1198.             j = i + amt
  1199.             s = self._line[i:j]
  1200.             self._line_offset = j
  1201.             self._line_left -= amt
  1202.             if self._line_left == 0:
  1203.                 self._done()
  1204.             
  1205.             return s
  1206.  
  1207.     
  1208.     def readline(self):
  1209.         if self._line_consumed:
  1210.             return self._file.readline()
  1211.         
  1212.         s = self._line[self._line_offset:]
  1213.         self._done()
  1214.         return s
  1215.  
  1216.     
  1217.     def readlines(self, size = None):
  1218.         if self._line_consumed:
  1219.             return self._file.readlines(size)
  1220.         
  1221.         L = [
  1222.             self._line[self._line_offset:]]
  1223.         self._done()
  1224.         if size is None:
  1225.             return L + self._file.readlines()
  1226.         else:
  1227.             return L + self._file.readlines(size)
  1228.  
  1229.  
  1230.  
  1231. def test():
  1232.     '''Test this module.
  1233.  
  1234.     A hodge podge of tests collected here, because they have too many
  1235.     external dependencies for the regular test suite.
  1236.     '''
  1237.     import sys
  1238.     import getopt
  1239.     (opts, args) = getopt.getopt(sys.argv[1:], 'd')
  1240.     dl = 0
  1241.     for o, a in opts:
  1242.         if o == '-d':
  1243.             dl = dl + 1
  1244.             continue
  1245.     
  1246.     host = 'www.python.org'
  1247.     selector = '/'
  1248.     if args[0:]:
  1249.         host = args[0]
  1250.     
  1251.     if args[1:]:
  1252.         selector = args[1]
  1253.     
  1254.     h = HTTP()
  1255.     h.set_debuglevel(dl)
  1256.     h.connect(host)
  1257.     h.putrequest('GET', selector)
  1258.     h.endheaders()
  1259.     (status, reason, headers) = h.getreply()
  1260.     print 'status =', status
  1261.     print 'reason =', reason
  1262.     print 'read', len(h.getfile().read())
  1263.     print 
  1264.     if headers:
  1265.         for header in headers.headers:
  1266.             print header.strip()
  1267.         
  1268.     
  1269.     print 
  1270.     
  1271.     class HTTP11(HTTP):
  1272.         _http_vsn = 11
  1273.         _http_vsn_str = 'HTTP/1.1'
  1274.  
  1275.     h = HTTP11('www.python.org')
  1276.     h.putrequest('GET', 'http://www.python.org/~jeremy/')
  1277.     h.endheaders()
  1278.     h.getreply()
  1279.     h.close()
  1280.     if hasattr(socket, 'ssl'):
  1281.         for host, selector in (('sourceforge.net', '/projects/python'),):
  1282.             print 'https://%s%s' % (host, selector)
  1283.             hs = HTTPS()
  1284.             hs.set_debuglevel(dl)
  1285.             hs.connect(host)
  1286.             hs.putrequest('GET', selector)
  1287.             hs.endheaders()
  1288.             (status, reason, headers) = hs.getreply()
  1289.             print 'status =', status
  1290.             print 'reason =', reason
  1291.             print 'read', len(hs.getfile().read())
  1292.             print 
  1293.             if headers:
  1294.                 for header in headers.headers:
  1295.                     print header.strip()
  1296.                 
  1297.             
  1298.             print 
  1299.         
  1300.     
  1301.  
  1302. if __name__ == '__main__':
  1303.     test()
  1304.  
  1305.